home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Tool Chest / Files / XTND 1.3.6 / Translator Examples / Text Translator / TextImport.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-23  |  13.2 KB  |  326 lines  |  [TEXT/MPS ]

  1. /************************************************************************
  2. *                                                                        *
  3. *    TextImport.c                                                        *
  4. *                                                                        *
  5. *    Translator for reading a text file with XTND 1.3.  This translator    *
  6. *    does not support headers, footers, pictures, or footnotes, since    *
  7. *    it reads only simple, unstructured ASCII files.                        *
  8. *                                                                        *
  9. *    Copyright © 1989,90 Claris Corporation                                *
  10. *    All Rights Reserved                                                    *
  11. *                                                                        *
  12. *    Author: Lyndley Crumly                                                *
  13. *    Date:   12 February, 1990                                            *
  14. *                                                                        *
  15. ************************************************************************/
  16.  
  17.  
  18. /**** Note: TextExport.π MUST be compiled and merged after this        ****/
  19. /**** project is compiled, since this project replaces the             ****/
  20. /**** resources in the Text translator when it is built, including    ****/
  21. /**** the resource created by TextExport.π.                            ****/
  22.  
  23. #include <StandardFile.h>
  24. #include <Fonts.h>
  25. #include <Memory.h>
  26. #include <Printing.h>
  27. enum { FALSE, TRUE };
  28.  
  29. #include ":::XTND Headers:XTNDCIncludes:XTNDTextTranslator.h"
  30.  
  31.  
  32. /*------------------------- Useful Constants ---------------------------*/
  33.  
  34. #define kTempBufferSize    512            /* Text buffer size                    */
  35. #define kFixedInch         0x00480000    /* 72 pixels in fixed format        */
  36. #define kSpaceChar         0x20        /* Space character in hex            */
  37.  
  38.  
  39. /*-------------------------Global Variables-----------------------------*/
  40.  
  41. /* The translator globals structure is used to store our import         */
  42. /* translator’s translator’s private global variables. A relocatable     */
  43. /* block is created in the application heap when the translator         */
  44. /* receives the IMPORT_INIT_ALL directive and a handle to the globals     */
  45. /* are stored in the GlobalHandle field of the Import Parameter Block     */
  46. /* passed into the translator from the application. The globals block     */
  47. /* is freed when the translator receives the IMPORT_CLOSE_ALL directive.*/
  48.  
  49. /* We are going to lock down the global handle when it is created and    */
  50. /* leave it that way so as to avoid any problems with dereferenced        */
  51. /* pointers.  You may choose to unlock the global handle when feasible.    */
  52.  
  53. typedef struct TransGlobals {
  54.     unsigned char     tempBuffer[kTempBufferSize];    /* Memory buffer where data from the disk file is stored */
  55.     Ptr                outPtr;                        /* Pointer into the text buffer which is passed to the application */
  56.     long            EOFPosition;                /* This is used to tell when we have reached the end of the data file */
  57.     long            bufferStart;                /* This stores the file position at which we started loading data */
  58.     long            charPos;                    /* This variable always indicates the next character to be read from the input data file */
  59.     Boolean         firstTime;                    /* Flag used to indicate whether this the first GetText call.  If it is the first GetText, then some initialization is done to set up the parameter block for subsequent GetText calls.                    */
  60. } TMyGlobals, *TMyGlobalPtr, **TMyGlobalHandle;
  61.  
  62.  
  63. /*-------------------------Function prototypes--------------------------*/
  64.  
  65.         void main(ImportParmBlkPtr importPBPtr);
  66. static    void InitAll(ImportParmBlkPtr importPBPtr, TMyGlobalHandle *myGlobals);
  67. static    void InitMain(ImportParmBlkPtr importPBPtr, TMyGlobalPtr myGlobalPtr);
  68. static    void GetText(ImportParmBlkPtr importPBPtr, TMyGlobalPtr myGlobalPtr);
  69. static    unsigned char GetNextChar(ImportParmBlkPtr importPBPtr, TMyGlobalPtr myGlobalPtr);
  70. static    void FillTempBuffer(long filepos, ImportParmBlkPtr importPBPtr, TMyGlobalPtr myGlobalPtr);
  71.  
  72.  
  73. /*----------------------------------------------------------------------*/
  74. /*    main    This is the main routine and the only entry point for the    */
  75. /*            the translator.  This routine actually performs all of the    */
  76. /*            work of the translator.  It dispatches the call to the         */
  77. /*            appropriate routine depending on the directive and             */
  78. /*            translator state.                                            */
  79. /*----------------------------------------------------------------------*/
  80. void main(register ImportParmBlkPtr importPBPtr)
  81. {
  82.     switch(importPBPtr->directive)
  83.     {
  84.         case importInitAll:        /* Initialize the translator.  This        */
  85.                                     /* must be the first call to the         */
  86.                                     /* must be the first call to the         */
  87.                                     /* translator.                            */
  88.             InitAll(importPBPtr, (TMyGlobalHandle *)&importPBPtr->globalHandle);
  89.             break;
  90.  
  91.         case importInitMain:        /* Initialize the main story.            */
  92.                                     /* Nothing needs to be done here.        */
  93.             importPBPtr->directive = importAcknowledge;
  94.             break;
  95.  
  96.         case importGetText:        /* Get the next text run from the main    */
  97.                                     /* body, since that is all we import.    */
  98.             GetText(importPBPtr, (TMyGlobalPtr)*importPBPtr->globalHandle);
  99.             break;
  100.  
  101.         case importCloseAll:        /* Shutdown the translator.  This must    */
  102.                                     /* be the last call to the translator.    */
  103.             if (importPBPtr->globalHandle) {
  104.                 DisposHandle(importPBPtr->globalHandle);
  105.                 (importPBPtr->globalHandle) = 0L;        /* nil */
  106.             }
  107.             break;
  108.  
  109.         default:                    /* We don't show the directives that we */
  110.             break;                    /* don't use. They are all taken care   */
  111.                                     /* of by default, which does nothing    */
  112.                                     /* at all.                                */
  113.     }
  114. }
  115.  
  116.  
  117. /*----------------------------------------------------------------------*/
  118. /*    InitAll    This routine performs all initialization for the            */
  119. /*            translator.  This must be the first call to the translator,    */
  120. /*            although this particular translator does not check to make    */
  121. /*            sure that this call was the first one made.                    */
  122. /*----------------------------------------------------------------------*/
  123. static void InitAll(register ImportParmBlkPtr importPBPtr, 
  124.                     register TMyGlobalHandle *myGlobals)
  125. {
  126.     /* First try to create a global handle and quit if we can't */
  127.  
  128.     if (!(*myGlobals = (TMyGlobalHandle)NewHandle(sizeof(TMyGlobals)))) {
  129.         importPBPtr->result = MemError();
  130.         return;
  131.     }
  132.  
  133.     /* Save the global handle in the field provided in the parameter block */
  134.     MoveHHi((Handle)*myGlobals);
  135.     HLock((Handle)*myGlobals);
  136.     importPBPtr->globalHandle = (Handle)*myGlobals;
  137.  
  138.     /* find the EOF position of the input file… */
  139.     if (importPBPtr->result = GetEOF(importPBPtr->refNum, &(***myGlobals).EOFPosition))
  140.         return;                                                    /* …can't do anything about this    */
  141.     (***myGlobals).bufferStart = (***myGlobals).EOFPosition;    /* So we know the buffer is empty    */
  142.     (***myGlobals).charPos = 0L;                                /* Start reading at the beginning of the file    */
  143.     (***myGlobals).firstTime = TRUE;
  144.  
  145.     /* Set initial values for fields in the import parameter block.        */
  146.     /* Some of these are purely arbitrary, and may be changed at your    */
  147.     /* discretion.                                                        */
  148.  
  149.     importPBPtr->numCols = 1;
  150.     importPBPtr->autoHyphenate = FALSE;
  151.     importPBPtr->topMargin = kFixedInch;
  152.     importPBPtr->bottomMargin = kFixedInch;
  153.     importPBPtr->leftMargin = kFixedInch;
  154.     importPBPtr->rightMargin = kFixedInch;
  155.     importPBPtr->gutter = 0x000C0000;
  156.     importPBPtr->startPageNum= 1;
  157.     importPBPtr->startFootnoteNum= 1;
  158.  
  159.     importPBPtr->rulerShowing= TRUE;
  160.     importPBPtr->doubleSided = FALSE;
  161.     importPBPtr->titlePage = FALSE;
  162.     importPBPtr->endnotes = FALSE;
  163.     importPBPtr->showInvisibles = FALSE;
  164.     importPBPtr->showPageGuides = FALSE;
  165.     importPBPtr->showPictures = TRUE;
  166.     importPBPtr->autoFootnotes = TRUE;
  167.     importPBPtr->smartQuotes = FALSE;
  168.     importPBPtr->fractCharWidths = FALSE;
  169. }
  170.  
  171.  
  172. /*----------------------------------------------------------------------*/
  173. /*    InitMain This routine performs some initialization when the first    */
  174. /*             GetText call is made, and not when the InitMain call is     */
  175. /*            made, as you might assume from the name.  The reason for    */
  176. /*             this is that these fields cannot be set before the first    */
  177. /*            GetText call, as they could be changed by the application.    */
  178. /*----------------------------------------------------------------------*/
  179. static void InitMain(register ImportParmBlkPtr importPBPtr, 
  180.                      register TMyGlobalPtr myGlobalPtr)
  181. {
  182.     /* Set initial values for fields in the import parameter block.        */
  183.     /* Some of these are purely arbitrary, and may be changed at your    */
  184.     /* discretion.                                                        */
  185.  
  186.     importPBPtr->txtFace = textPlain;
  187.     importPBPtr->txtSize = 12;
  188.     importPBPtr->txtFont = applFont;
  189.     importPBPtr->txtColor = textBlack;
  190.     importPBPtr->txtJust = textLeft;
  191.  
  192.     importPBPtr->paraFmts[0] = 0;                /* Left Paragraph Margin    */
  193.     importPBPtr->paraFmts[1] = 0;                /* Left Paragraph Indent    */
  194.     importPBPtr->paraFmts[2] = 0;                /* Right Paragraph Margin    */
  195.     importPBPtr->paraFmts[3] = 0;                /* Single Line Spacing        */
  196.     importPBPtr->paraFmts[4] = 0;                /* No Space Before            */
  197.     importPBPtr->paraFmts[5] = 0;                /* No Space After            */
  198.     importPBPtr->paraFmts[6] = -1;                /* Fixed Line Spacing        */
  199.     importPBPtr->paraFmts[7] = 0;                /* Fixed Point Spacing        */
  200.     importPBPtr->paraFmts[8] = 0;                /* Fixed Point Spacing        */
  201.  
  202.     importPBPtr->tabs[0].tabIndent = -1;        /* First tab setting, which    */
  203.                                                 /* means there are no tabs.    */
  204.  
  205.     myGlobalPtr->firstTime = FALSE;            /* Don't come back here again    */
  206. }
  207.  
  208.  
  209. /*----------------------------------------------------------------------*/
  210. /*    GetText    This routine reads the next text run and returns it to the    */
  211. /*            application.
  212. /*----------------------------------------------------------------------*/
  213. static void GetText(register ImportParmBlkPtr importPBPtr, 
  214.                     register TMyGlobalPtr myGlobalPtr)
  215. {
  216.     unsigned char ch;            /* The next character from the text buffer    */
  217.     short count = 0;            /* The number of characters we will return    */
  218.     Boolean    endOfRun = FALSE;    /* Indicates the end of the text run    */
  219.  
  220.     if (myGlobalPtr->firstTime)    /* Initialize text fields on the first GetText call    */
  221.             InitMain(importPBPtr, myGlobalPtr);
  222.  
  223.     /* Set up a pointer into our output buffer.  This pointer is         */
  224.     /* incremented as each character is added to the buffer.            */
  225.  
  226.     myGlobalPtr->outPtr = importPBPtr->textBuffer;
  227.  
  228.     /* Read characters until we reach the end of the run, which has a    */
  229.     /* maximum length of 255 characters and must end at the end of the    */
  230.     /* file (just to make things simpler).                                */
  231.  
  232.     while (myGlobalPtr->charPos < myGlobalPtr->EOFPosition && count < 255 && !endOfRun) {
  233.         if (importPBPtr->result) {                /* If we got a read error,    */
  234.             count = -1;                            /* Terminate the import        */
  235.             break;
  236.         }
  237.  
  238.         ch = GetNextChar(importPBPtr, myGlobalPtr);    /* Retrieve the next character    */
  239.  
  240.         /* Characters below the space character are not returned, with    */
  241.         /* the exception of the space, new page and return characters.    */
  242.         
  243.         if (ch < kSpaceChar) {
  244.             if (ch == tabChar || ch == newPage || ch == returnChar) {
  245.                 *(myGlobalPtr->outPtr) = ch;        /* Return these characters unchanged    */
  246.                 (myGlobalPtr->outPtr)++;
  247.                 count++;
  248.             }
  249.             if (ch == returnChar || ch == newPage)
  250.                 endOfRun = TRUE;    /* These characters end a text run    */
  251.  
  252.         /* All other characters are returned unchanged, except for         */
  253.         /* 0x7F, which is not a valid character in the Macintosh         */
  254.         /* character set. (It's a delete character or something.)        */
  255.  
  256.         } else {
  257.             if (ch != 0x7F) {
  258.                 *(myGlobalPtr->outPtr) = ch;
  259.                 (myGlobalPtr->outPtr)++;
  260.                 count++;
  261.             }
  262.         }
  263.     }
  264.  
  265.     if (count <= 0)                    /* If no data was found to be returned    */
  266.          importPBPtr->directive = importAcknowledge;        /* End of data    */
  267.  
  268.     importPBPtr->textLength = count;
  269. }
  270.  
  271.  
  272. /*----------------------------------------------------------------------*/
  273. /*    GetNextChar    This routine retrieves the next character from the text    */
  274. /*            buffer and returns it, automatically incrementing charPos.    */
  275. /*----------------------------------------------------------------------*/
  276. static unsigned char GetNextChar(register ImportParmBlkPtr importPBPtr, 
  277.                                  register TMyGlobalPtr myGlobalPtr)
  278. {
  279.     short bufferpos;
  280.  
  281.     if (myGlobalPtr->charPos >= myGlobalPtr->EOFPosition)            /* If we are reading past end of file    */
  282.         return(-1);                                                    /* Return some arbitrary invalid character    */
  283.  
  284.     bufferpos = myGlobalPtr->charPos - myGlobalPtr->bufferStart;    /* Find our position in buffer    */
  285.  
  286.     /* If bufferpos is outside the buffer, then the buffer does not        */
  287.     /* contain the requested character.  The buffer will be refilled    */
  288.     /* from the file starting at the requested character.                */
  289.     
  290.     if ((bufferpos < 0) || (bufferpos >= kTempBufferSize)) {
  291.         FillTempBuffer(myGlobalPtr->charPos, importPBPtr, myGlobalPtr);    /* Fill the buffer from the file    */
  292.         myGlobalPtr->bufferStart = myGlobalPtr->charPos;
  293.         bufferpos = 0;
  294.     }
  295.     myGlobalPtr->charPos++;                            /* Increment charPos for next call    */
  296.  
  297.     return((myGlobalPtr->tempBuffer)[bufferpos]);    /* Return the requested character    */
  298. }
  299.  
  300.  
  301. /*----------------------------------------------------------------------*/
  302. /*    FillTempBuffer    This routine fills the temporary buffer starting    */
  303. /*                 at the given position in the data file.                    */
  304. /*----------------------------------------------------------------------*/
  305. static void FillTempBuffer(long filepos, 
  306.                            register ImportParmBlkPtr importPBPtr, 
  307.                            register TMyGlobalPtr myGlobalPtr)
  308. {
  309.     long bytes;
  310.     short readcount;
  311.  
  312.     if (importPBPtr->result) return;                /* Cancel if a previous error exists    */
  313.     readcount = kTempBufferSize ;                    /* Use constant to set buffer size    */
  314.  
  315.     if (myGlobalPtr->EOFPosition < filepos + readcount)        /* Make sure we don't read    */
  316.         readcount = myGlobalPtr->EOFPosition - filepos;        /* past the end of file        */
  317.  
  318.     bytes = readcount;
  319.  
  320.     /* Set the file position at which to start reading */
  321.     if (importPBPtr->result = SetFPos(importPBPtr->refNum, fsFromStart, filepos)) return;
  322.  
  323.     /* Read the data into the temporary buffer */
  324.     importPBPtr->result = FSRead(importPBPtr->refNum, &bytes, myGlobalPtr->tempBuffer);
  325. }
  326.